@@ -1,14 +1,26 @@  | 
            ||
| 1 | 1 | 
                # -*- coding: utf-8 -*-  | 
            
| 2 | 2 | 
                 | 
            
| 3 | 3 | 
                from django.contrib import admin  | 
            
| 4 | 
                +from django.contrib.auth.hashers import make_password  | 
            |
| 4 | 5 | 
                 | 
            
| 5 | 6 | 
                from account.models import LensmanInfo  | 
            
| 6 | 7 | 
                 | 
            
| 8 | 
                +from utils.uuid_utils import curtailUUID  | 
            |
| 9 | 
                +  | 
            |
| 7 | 10 | 
                 | 
            
| 8 | 11 | 
                class LensmanInfoAdmin(admin.ModelAdmin):  | 
            
| 12 | 
                +    readonly_fields = ('lensman_id', 'encryption', )
               | 
            |
| 9 | 13 | 
                     list_display = ('lensman_id', 'name', 'sex', 'phone', 'location', 'proportion', 'status', 'created_at', 'updated_at')
               | 
            
| 10 | 14 | 
                     search_fields = ('name', 'phone', 'location')
               | 
            
| 11 | 15 | 
                     list_filter = ('sex', 'status')
               | 
            
| 12 | 16 | 
                 | 
            
| 17 | 
                + def save_model(self, request, obj, form, change):  | 
            |
| 18 | 
                + if not obj.lensman_id:  | 
            |
| 19 | 
                + obj.lensman_id = curtailUUID(LensmanInfo, 'lensman_id')  | 
            |
| 20 | 
                + if obj.password:  | 
            |
| 21 | 
                + obj.encryption = make_password(obj.password, None, 'pbkdf2_sha256')  | 
            |
| 22 | 
                + obj.password = None  | 
            |
| 23 | 
                + obj.save()  | 
            |
| 24 | 
                +  | 
            |
| 13 | 25 | 
                 | 
            
| 14 | 26 | 
                admin.site.register(LensmanInfo, LensmanInfoAdmin)  | 
            
                @@ -0,0 +1,29 @@  | 
            ||
| 1 | 
                +# -*- coding: utf-8 -*-  | 
            |
| 2 | 
                +from __future__ import unicode_literals  | 
            |
| 3 | 
                +  | 
            |
| 4 | 
                +from django.db import models, migrations  | 
            |
| 5 | 
                +  | 
            |
| 6 | 
                +  | 
            |
| 7 | 
                +class Migration(migrations.Migration):  | 
            |
| 8 | 
                +  | 
            |
| 9 | 
                + dependencies = [  | 
            |
| 10 | 
                +        ('account', '0001_initial'),
               | 
            |
| 11 | 
                + ]  | 
            |
| 12 | 
                +  | 
            |
| 13 | 
                + operations = [  | 
            |
| 14 | 
                + migrations.AddField(  | 
            |
| 15 | 
                + model_name='lensmaninfo',  | 
            |
| 16 | 
                + name='encryption',  | 
            |
| 17 | 
                + field=models.CharField(help_text='\u6444\u5f71\u5e08\u5bc6\u7801', max_length=255, null=True, verbose_name='encryption', blank=True),  | 
            |
| 18 | 
                + ),  | 
            |
| 19 | 
                + migrations.AddField(  | 
            |
| 20 | 
                + model_name='lensmaninfo',  | 
            |
| 21 | 
                + name='password',  | 
            |
| 22 | 
                + field=models.CharField(help_text='\u6444\u5f71\u5e08\u5bc6\u7801', max_length=255, null=True, verbose_name='password', blank=True),  | 
            |
| 23 | 
                + ),  | 
            |
| 24 | 
                + migrations.AddField(  | 
            |
| 25 | 
                + model_name='lensmaninfo',  | 
            |
| 26 | 
                + name='username',  | 
            |
| 27 | 
                + field=models.CharField(null=True, max_length=255, blank=True, help_text='\u6444\u5f71\u5e08\u7528\u6237\u540d', unique=True, verbose_name='username', db_index=True),  | 
            |
| 28 | 
                + ),  | 
            |
| 29 | 
                + ]  | 
            
                @@ -0,0 +1,19 @@  | 
            ||
| 1 | 
                +# -*- coding: utf-8 -*-  | 
            |
| 2 | 
                +from __future__ import unicode_literals  | 
            |
| 3 | 
                +  | 
            |
| 4 | 
                +from django.db import models, migrations  | 
            |
| 5 | 
                +  | 
            |
| 6 | 
                +  | 
            |
| 7 | 
                +class Migration(migrations.Migration):  | 
            |
| 8 | 
                +  | 
            |
| 9 | 
                + dependencies = [  | 
            |
| 10 | 
                +        ('account', '0002_auto_20151202_2251'),
               | 
            |
| 11 | 
                + ]  | 
            |
| 12 | 
                +  | 
            |
| 13 | 
                + operations = [  | 
            |
| 14 | 
                + migrations.AlterField(  | 
            |
| 15 | 
                + model_name='lensmaninfo',  | 
            |
| 16 | 
                + name='lensman_id',  | 
            |
| 17 | 
                + field=models.CharField(help_text='\u6444\u5f71\u5e08\u552f\u4e00\u6807\u8bc6', unique=True, max_length=255, verbose_name='lensman_id', db_index=True),  | 
            |
| 18 | 
                + ),  | 
            |
| 19 | 
                + ]  | 
            
                @@ -5,8 +5,6 @@ from django.utils.translation import ugettext_lazy as _  | 
            ||
| 5 | 5 | 
                 | 
            
| 6 | 6 | 
                from pai2.basemodels import CreateUpdateMixin  | 
            
| 7 | 7 | 
                 | 
            
| 8 | 
                -from shortuuidfield import ShortUUIDField  | 
            |
| 9 | 
                -  | 
            |
| 10 | 8 | 
                 | 
            
| 11 | 9 | 
                class LensmanInfo(CreateUpdateMixin):  | 
            
| 12 | 10 | 
                MALE = 0  | 
            
                @@ -17,7 +15,12 @@ class LensmanInfo(CreateUpdateMixin):  | 
            ||
| 17 | 15 | 
                (FEMALE, u'女'),  | 
            
| 18 | 16 | 
                )  | 
            
| 19 | 17 | 
                 | 
            
| 20 | 
                - lensman_id = ShortUUIDField(_(u'lensman_id'), max_length=255, help_text=u'摄影师唯一标识', db_index=True)  | 
            |
| 18 | 
                + lensman_id = models.CharField(_(u'lensman_id'), max_length=255, blank=True, null=True, help_text=u'摄影师唯一标识', db_index=True, unique=True)  | 
            |
| 19 | 
                +  | 
            |
| 20 | 
                + username = models.CharField(_(u'username'), max_length=255, blank=True, null=True, help_text=u'摄影师用户名', db_index=True, unique=True)  | 
            |
| 21 | 
                + password = models.CharField(_(u'password'), max_length=255, blank=True, null=True, help_text=u'摄影师密码')  | 
            |
| 22 | 
                + encryption = models.CharField(_(u'encryption'), max_length=255, blank=True, null=True, help_text=u'摄影师密码')  | 
            |
| 23 | 
                +  | 
            |
| 21 | 24 | 
                name = models.CharField(_(u'name'), max_length=255, blank=True, null=True, help_text=u'摄影师姓名')  | 
            
| 22 | 25 | 
                sex = models.IntegerField(_(u'sex'), choices=SEX_TYPE, default=MALE, help_text=u'摄影师性别')  | 
            
| 23 | 26 | 
                phone = models.CharField(_(u'phone'), max_length=255, blank=True, null=True, help_text=u'摄影师电话', db_index=True, unique=True)  | 
            
                @@ -1,12 +1,43 @@  | 
            ||
| 1 | 1 | 
                # -*- coding: utf-8 -*-  | 
            
| 2 | 2 | 
                 | 
            
| 3 | 
                +from django.contrib.auth.hashers import check_password  | 
            |
| 3 | 4 | 
                from django.contrib.auth.models import User, Group  | 
            
| 5 | 
                +from django.http import JsonResponse  | 
            |
| 6 | 
                +  | 
            |
| 4 | 7 | 
                from rest_framework import viewsets  | 
            
| 5 | 8 | 
                 | 
            
| 6 | 9 | 
                from account.models import LensmanInfo  | 
            
| 7 | 10 | 
                from account.serializers import UserSerializer, GroupSerializer, LensmanInfoSerializer  | 
            
| 8 | 11 | 
                 | 
            
| 9 | 12 | 
                 | 
            
| 13 | 
                +# curl -X POST -F username=xxxxxxx -F password=xxxxxxx http://api.xfoto.com.cn/login  | 
            |
| 14 | 
                +def user_login(request):  | 
            |
| 15 | 
                +    username = request.POST.get('username', '')
               | 
            |
| 16 | 
                +    password = request.POST.get('password', '')
               | 
            |
| 17 | 
                +  | 
            |
| 18 | 
                + try:  | 
            |
| 19 | 
                + lensman = LensmanInfo.objects.get(username=username)  | 
            |
| 20 | 
                + except LensmanInfo.DoesNotExist:  | 
            |
| 21 | 
                +        return JsonResponse({
               | 
            |
| 22 | 
                + 'status': 4000,  | 
            |
| 23 | 
                + 'message': u'用户不存在',  | 
            |
| 24 | 
                + })  | 
            |
| 25 | 
                +  | 
            |
| 26 | 
                + if not check_password(password, lensman.encryption):  | 
            |
| 27 | 
                +        return JsonResponse({
               | 
            |
| 28 | 
                + 'status': 4001,  | 
            |
| 29 | 
                + 'message': u'用户密码错误',  | 
            |
| 30 | 
                + })  | 
            |
| 31 | 
                +  | 
            |
| 32 | 
                +    return JsonResponse({
               | 
            |
| 33 | 
                + 'status': 200,  | 
            |
| 34 | 
                + 'message': u'登录成功',  | 
            |
| 35 | 
                +        'data': {
               | 
            |
| 36 | 
                + 'user': lensman.lensman_id  | 
            |
| 37 | 
                + },  | 
            |
| 38 | 
                + })  | 
            |
| 39 | 
                +  | 
            |
| 40 | 
                +  | 
            |
| 10 | 41 | 
                class UserViewSet(viewsets.ModelViewSet):  | 
            
| 11 | 42 | 
                """  | 
            
| 12 | 43 | 
                API endpoint that allows users to be viewed or edited.  | 
            
                @@ -2,10 +2,15 @@  | 
            ||
| 2 | 2 | 
                 | 
            
| 3 | 3 | 
                from django.conf.urls import url  | 
            
| 4 | 4 | 
                 | 
            
| 5 | 
                +from account import views as account_views  | 
            |
| 5 | 6 | 
                from photo import views as photo_views  | 
            
| 6 | 7 | 
                 | 
            
| 7 | 8 | 
                 | 
            
| 8 | 9 | 
                urlpatterns = [  | 
            
| 10 | 
                + url(r'^login$', account_views.user_login, name='user_login'),  | 
            |
| 11 | 
                +]  | 
            |
| 12 | 
                +  | 
            |
| 13 | 
                +urlpatterns += [  | 
            |
| 9 | 14 | 
                url(r'^uuid_init$', photo_views.uuid_init, name='uuid_init'),  | 
            
| 10 | 15 | 
                url(r'^uuid$', photo_views.uuid, name='uuid'),  | 
            
| 11 | 16 | 
                url(r'^photos/upload$', photo_views.upload_photo, name='upload_photo'),  | 
            
                @@ -1,4 +1,8 @@  | 
            ||
| 1 | 
                -1、照片上传 —— 401  | 
            |
| 2 | 
                - 4010 —— 参数错误  | 
            |
| 3 | 
                - 4011 —— 摄影师不存在  | 
            |
| 4 | 
                - 4012 —— 照片已存在  | 
            |
| 1 | 
                +1、用户信息 —— 400  | 
            |
| 2 | 
                + 4000 —— 用户不存在  | 
            |
| 3 | 
                + 4001 —— 用户密码错误  | 
            |
| 4 | 
                +  | 
            |
| 5 | 
                +2、照片上传 —— 401  | 
            |
| 6 | 
                + 4010 —— 参数错误  | 
            |
| 7 | 
                + 4011 —— 摄影师不存在  | 
            |
| 8 | 
                + 4012 —— 照片已存在  | 
            
                @@ -46,6 +46,8 @@ INSTALLED_APPS = (  | 
            ||
| 46 | 46 | 
                'photo',  | 
            
| 47 | 47 | 
                )  | 
            
| 48 | 48 | 
                 | 
            
| 49 | 
                +INSTALLED_APPS += ('multidomain', )
               | 
            |
| 50 | 
                +  | 
            |
| 49 | 51 | 
                MIDDLEWARE_CLASSES = (  | 
            
| 50 | 52 | 
                'django.contrib.sessions.middleware.SessionMiddleware',  | 
            
| 51 | 53 | 
                'django.middleware.common.CommonMiddleware',  | 
            
                @@ -57,6 +59,13 @@ MIDDLEWARE_CLASSES = (  | 
            ||
| 57 | 59 | 
                'django.middleware.security.SecurityMiddleware',  | 
            
| 58 | 60 | 
                )  | 
            
| 59 | 61 | 
                 | 
            
| 62 | 
                +MIDDLEWARE_CLASSES += ('multidomain.middleware.DomainMiddleware', )
               | 
            |
| 63 | 
                +  | 
            |
| 64 | 
                +URL_CONFIG = (  | 
            |
| 65 | 
                + # (r'^(.+\.)?xfoto\.com\.cn', 'pai2.urls_www'),  | 
            |
| 66 | 
                + (r'^(.+\.)?api\.xfoto\.com\.cn', 'pai2.urls_api'),  | 
            |
| 67 | 
                +)  | 
            |
| 68 | 
                +  | 
            |
| 60 | 69 | 
                ROOT_URLCONF = 'pai2.urls'  | 
            
| 61 | 70 | 
                 | 
            
| 62 | 71 | 
                TEMPLATES = [  | 
            
                @@ -138,6 +147,9 @@ REST_FRAMEWORK = {
               | 
            ||
| 138 | 147 | 
                'PAGE_SIZE': 1  | 
            
| 139 | 148 | 
                }  | 
            
| 140 | 149 | 
                 | 
            
| 150 | 
                +# 唯一标识设置  | 
            |
| 151 | 
                +CURTAIL_UUID_LENGTH = 7  | 
            |
| 152 | 
                +  | 
            |
| 141 | 153 | 
                # 域名设置  | 
            
| 142 | 154 | 
                DOMAIN = 'http://xfoto.com.cn'  | 
            
| 143 | 155 | 
                 | 
            
                @@ -33,14 +33,18 @@ urlpatterns = [  | 
            ||
| 33 | 33 | 
                ]  | 
            
| 34 | 34 | 
                 | 
            
| 35 | 35 | 
                urlpatterns += [  | 
            
| 36 | 
                -    url(r'^api/', include('api.urls', namespace='api')),
               | 
            |
| 37 | 
                -    # url(r'^photo/', include('photo.urls', namespace='photo'))
               | 
            |
| 36 | 
                +    # url(r'^api/', include('api.urls', namespace='api')),
               | 
            |
| 37 | 
                + url(r'^s/(?P<session>\w+)$', photo_views.session_detail, name='session_detail'),  | 
            |
| 38 | 
                + url(r'^p/(?P<photo>\w+)$', photo_views.photo_standard, name='photo_standard'), # standard thumbnail, available for free  | 
            |
| 39 | 
                + url(r'^m/(?P<photo>\w+)$', photo_views.photo_medium, name='photo_medium'), # medium/mobile version, without watermark, login or paid by others  | 
            |
| 40 | 
                + url(r'^l/(?P<photo>\w+)$', photo_views.photo_large, name='photo_large'), # large, might support server side panning later, login required  | 
            |
| 41 | 
                + url(r'^r/(?P<photo>\w+)$', photo_views.photo_raw, name='photo_raw'), # raw image, only for finishers  | 
            |
| 38 | 42 | 
                ]  | 
            
| 39 | 43 | 
                 | 
            
| 40 | 44 | 
                # Wire up our API using automatic URL routing.  | 
            
| 41 | 45 | 
                # Additionally, we include login URLs for the browsable API.  | 
            
| 42 | 46 | 
                urlpatterns += [  | 
            
| 43 | 
                - url(r'^apihome/', include(router.urls)),  | 
            |
| 47 | 
                + url(r'^api/', include(router.urls)),  | 
            |
| 44 | 48 | 
                     url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
               | 
            
| 45 | 49 | 
                ]  | 
            
| 46 | 50 | 
                 | 
            
                @@ -0,0 +1,10 @@  | 
            ||
| 1 | 
                +# -*- coding: utf-8 -*-  | 
            |
| 2 | 
                +  | 
            |
| 3 | 
                +  | 
            |
| 4 | 
                +from django.conf import settings  | 
            |
| 5 | 
                +from django.conf.urls import include, url  | 
            |
| 6 | 
                +  | 
            |
| 7 | 
                +  | 
            |
| 8 | 
                +urlpatterns = [  | 
            |
| 9 | 
                +    url(r'^', include('api.urls', namespace='api')),
               | 
            |
| 10 | 
                +]  | 
            
                @@ -26,10 +26,6 @@ server {
               | 
            ||
| 26 | 26 | 
                alias /home/paiai/work/pai2/collect_static; # your Django project's static files - amend as required  | 
            
| 27 | 27 | 
                }  | 
            
| 28 | 28 | 
                 | 
            
| 29 | 
                -    location /p/  {
               | 
            |
| 30 | 
                - alias /home/paiai/work/pai2/media/photo; # Photo  | 
            |
| 31 | 
                - }  | 
            |
| 32 | 
                -  | 
            |
| 33 | 29 | 
                # Finally, send all non-media requests to the Django server.  | 
            
| 34 | 30 | 
                     location / {
               | 
            
| 35 | 31 | 
                # uwsgi_pass pai2;  | 
            
                @@ -47,16 +47,16 @@ class PhotosInfo(CreateUpdateMixin):  | 
            ||
| 47 | 47 | 
                 | 
            
| 48 | 48 | 
                @property  | 
            
| 49 | 49 | 
                def photo_url(self):  | 
            
| 50 | 
                -        # return u'{0}/media/{1}'.format(settings.DOMAIN, self.photo_path) if self.photo_path else ''
               | 
            |
| 51 | 
                -        return u'{0}/p/{1}'.format(settings.DOMAIN, self.photo_name) if self.photo_name else ''
               | 
            |
| 50 | 
                +        return u'{0}/media/{1}'.format(settings.DOMAIN, self.photo_path) if self.photo_path else ''
               | 
            |
| 51 | 
                +        # return u'{0}/p/{1}'.format(settings.DOMAIN, self.photo_name) if self.photo_name else ''
               | 
            |
| 52 | 52 | 
                 | 
            
| 53 | 53 | 
                def _data(self):  | 
            
| 54 | 54 | 
                         return {
               | 
            
| 55 | 55 | 
                'pk': self.pk,  | 
            
| 56 | 
                - 'lensman_id': self.lensman_id,  | 
            |
| 57 | 
                - 'session_id': self.session_id,  | 
            |
| 58 | 
                - 'photo_id': self.photo_id,  | 
            |
| 59 | 
                - 'photo_url': self.photo_url,  | 
            |
| 56 | 
                + 'user': self.lensman_id,  | 
            |
| 57 | 
                + 'session': self.session_id,  | 
            |
| 58 | 
                + 'photo': self.photo_id,  | 
            |
| 59 | 
                + # 'photo_url': self.photo_url,  | 
            |
| 60 | 60 | 
                }  | 
            
| 61 | 61 | 
                 | 
            
| 62 | 62 | 
                data = property(_data)  | 
            
                @@ -0,0 +1,10 @@  | 
            ||
| 1 | 
                +<!DOCTYPE html>  | 
            |
| 2 | 
                +<html>  | 
            |
| 3 | 
                +<head lang="en">  | 
            |
| 4 | 
                + <meta charset="UTF-8">  | 
            |
| 5 | 
                + <title></title>  | 
            |
| 6 | 
                +</head>  | 
            |
| 7 | 
                +<body>  | 
            |
| 8 | 
                +    <img src="{{ photo_url }}">
               | 
            |
| 9 | 
                +</body>  | 
            |
| 10 | 
                +</html>  | 
            
                @@ -0,0 +1,12 @@  | 
            ||
| 1 | 
                +<!DOCTYPE html>  | 
            |
| 2 | 
                +<html>  | 
            |
| 3 | 
                +<head lang="en">  | 
            |
| 4 | 
                + <meta charset="UTF-8">  | 
            |
| 5 | 
                + <title></title>  | 
            |
| 6 | 
                +</head>  | 
            |
| 7 | 
                +<body>  | 
            |
| 8 | 
                +    {% for photo in photos %}
               | 
            |
| 9 | 
                +    <div><img src="{{ photo.photo_url }}"></div>
               | 
            |
| 10 | 
                +    {% endfor %}
               | 
            |
| 11 | 
                +</body>  | 
            |
| 12 | 
                +</html>  | 
            
                @@ -3,6 +3,7 @@  | 
            ||
| 3 | 3 | 
                from django.core.files.storage import default_storage  | 
            
| 4 | 4 | 
                from django.db import transaction  | 
            
| 5 | 5 | 
                from django.http import JsonResponse  | 
            
| 6 | 
                +from django.shortcuts import render, redirect  | 
            |
| 6 | 7 | 
                 | 
            
| 7 | 8 | 
                from rest_framework import viewsets  | 
            
| 8 | 9 | 
                 | 
            
                @@ -19,7 +20,7 @@ def uuid_init(request):  | 
            ||
| 19 | 20 | 
                     num = int(request.GET.get('num', 1000))
               | 
            
| 20 | 21 | 
                 | 
            
| 21 | 22 | 
                for i in xrange(num):  | 
            
| 22 | 
                - UUIDInfo.objects.create(uuid=curtailUUID())  | 
            |
| 23 | 
                + UUIDInfo.objects.create(uuid=curtailUUID(UUIDInfo))  | 
            |
| 23 | 24 | 
                 | 
            
| 24 | 25 | 
                     return JsonResponse({
               | 
            
| 25 | 26 | 
                'status': 200,  | 
            
                @@ -28,10 +29,10 @@ def uuid_init(request):  | 
            ||
| 28 | 29 | 
                })  | 
            
| 29 | 30 | 
                 | 
            
| 30 | 31 | 
                 | 
            
| 31 | 
                -# curl -X POST -F lensman_id=123 -F num=100 http://xfoto.com.cn/api/uuid  | 
            |
| 32 | 
                +# curl -X POST -F user=xxxxxxx -F num=100 http://api.xfoto.com.cn/uuid  | 
            |
| 32 | 33 | 
                @transaction.atomic  | 
            
| 33 | 34 | 
                def uuid(request):  | 
            
| 34 | 
                -    lensman_id = request.POST.get('lensman_id', '')
               | 
            |
| 35 | 
                +    lensman_id = request.POST.get('user', '')
               | 
            |
| 35 | 36 | 
                     num = int(request.POST.get('num', 100))
               | 
            
| 36 | 37 | 
                 | 
            
| 37 | 38 | 
                uuids = UUIDInfo.objects.select_for_update().filter(status=True)[:num]  | 
            
                @@ -58,10 +59,10 @@ def uuid(request):  | 
            ||
| 58 | 59 | 
                # name with the symbol <. The difference between @ and < is then that @ makes a file get attached in the post as a file upload,  | 
            
| 59 | 60 | 
                # while the < makes a text field and just get the contents for that text field from a file.  | 
            
| 60 | 61 | 
                #  | 
            
| 61 | 
                -# curl -X POST -F lensman_id=123 -F session_id=456 -F photo=@7056288a9ddf2db294cf50a943920989.jpg;filename=789 http://xfoto.com.cn/api/photos/upload  | 
            |
| 62 | 
                +# curl -X POST -F user=xxxxxxx -F session=xxxxxxx -F photo=@xxxxxxx.jpg http://api.xfoto.com.cn/photos/upload  | 
            |
| 62 | 63 | 
                def upload_photo(request):  | 
            
| 63 | 
                -    lensman_id = request.POST.get('lensman_id', '')
               | 
            |
| 64 | 
                -    session_id = request.POST.get('session_id', '')
               | 
            |
| 64 | 
                +    lensman_id = request.POST.get('user', '')
               | 
            |
| 65 | 
                +    session_id = request.POST.get('session', '')
               | 
            |
| 65 | 66 | 
                 | 
            
| 66 | 67 | 
                     photo = request.FILES.get('photo', '')
               | 
            
| 67 | 68 | 
                 | 
            
                @@ -79,7 +80,7 @@ def upload_photo(request):  | 
            ||
| 79 | 80 | 
                'message': u'摄影师不存在',  | 
            
| 80 | 81 | 
                })  | 
            
| 81 | 82 | 
                 | 
            
| 82 | 
                - photo_id = curtailUUID()  | 
            |
| 83 | 
                + photo_id = curtailUUID(PhotosInfo, 'photo_id')  | 
            |
| 83 | 84 | 
                 | 
            
| 84 | 85 | 
                _, extension = os.path.splitext(photo.name)  | 
            
| 85 | 86 | 
                     # photo_path = 'photo/{0}/{1}/{2}{3}'.format(lensman_id, session_id, photo_id, extension)
               | 
            
                @@ -105,6 +106,31 @@ def upload_photo(request):  | 
            ||
| 105 | 106 | 
                })  | 
            
| 106 | 107 | 
                 | 
            
| 107 | 108 | 
                 | 
            
| 109 | 
                +def session_detail(request, session):  | 
            |
| 110 | 
                + photos = PhotosInfo.objects.filter(session_id=session)  | 
            |
| 111 | 
                +    return render(request, 'photo/session_detail.html', {'photos': photos})
               | 
            |
| 112 | 
                +  | 
            |
| 113 | 
                +  | 
            |
| 114 | 
                +def photo_standard(request, photo):  | 
            |
| 115 | 
                + photo = PhotosInfo.objects.get(photo_id=photo)  | 
            |
| 116 | 
                +    return render(request, 'photo/photo_detail.html', {'photo_url': photo.photo_url})
               | 
            |
| 117 | 
                +  | 
            |
| 118 | 
                +  | 
            |
| 119 | 
                +def photo_medium(request, photo):  | 
            |
| 120 | 
                + photo = PhotosInfo.objects.get(photo_id=photo)  | 
            |
| 121 | 
                +    return render(request, 'photo/photo_detail.html', {'photo_url': photo.photo_url})
               | 
            |
| 122 | 
                +  | 
            |
| 123 | 
                +  | 
            |
| 124 | 
                +def photo_large(request, photo):  | 
            |
| 125 | 
                + photo = PhotosInfo.objects.get(photo_id=photo)  | 
            |
| 126 | 
                +    return render(request, 'photo/photo_detail.html', {'photo_url': photo.photo_url})
               | 
            |
| 127 | 
                +  | 
            |
| 128 | 
                +  | 
            |
| 129 | 
                +def photo_raw(request, photo):  | 
            |
| 130 | 
                + photo = PhotosInfo.objects.get(photo_id=photo)  | 
            |
| 131 | 
                +    return render(request, 'photo/photo_detail.html', {'photo_url': photo.photo_url})
               | 
            |
| 132 | 
                +  | 
            |
| 133 | 
                +  | 
            |
| 108 | 134 | 
                class PhotoInfoViewSet(viewsets.ModelViewSet):  | 
            
| 109 | 135 | 
                     queryset = PhotosInfo.objects.all().order_by('-created_at')
               | 
            
| 110 | 136 | 
                serializer_class = PhotosInfoSerializer  | 
            
                @@ -1,16 +1,18 @@  | 
            ||
| 1 | 1 | 
                # -*- coding: utf-8 -*-  | 
            
| 2 | 2 | 
                 | 
            
| 3 | 
                +from django.conf import settings  | 
            |
| 4 | 
                +  | 
            |
| 3 | 5 | 
                from photo.models import UUIDInfo  | 
            
| 4 | 6 | 
                 | 
            
| 5 | 7 | 
                import shortuuid  | 
            
| 6 | 8 | 
                 | 
            
| 7 | 9 | 
                 | 
            
| 8 | 
                -def curtailUUID(length=10):  | 
            |
| 10 | 
                +def curtailUUID(model, field='uuid', length=settings.CURTAIL_UUID_LENGTH):  | 
            |
| 9 | 11 | 
                flag = True  | 
            
| 10 | 12 | 
                while flag:  | 
            
| 11 | 13 | 
                uuid = shortuuid.uuid()[-length:]  | 
            
| 12 | 14 | 
                try:  | 
            
| 13 | 
                - UUIDInfo.objects.get(uuid=uuid)  | 
            |
| 14 | 
                - except UUIDInfo.DoesNotExist:  | 
            |
| 15 | 
                +            model.objects.get(**{field: uuid})
               | 
            |
| 16 | 
                + except model.DoesNotExist:  | 
            |
| 15 | 17 | 
                flag = False  | 
            
| 16 | 18 | 
                return uuid  |